/*
 * Middleware
 * Copyright (C) 2010/11
 * Riccardo Pulvirenti, Giuseppe Ravidà, Andrea Tino
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANDABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program. If not, see http://www.gnu.org/licenses
 */

/*!
 * File: task_descriptor.hpp
 */

#ifndef _TASK_DESCRIPTOR_HPP_
#define _TASK_DESCRIPTOR_HPP_

#include <iostream>
#include <string>
#include <boost/archive/text_oarchive.hpp>
#include <boost/archive/text_iarchive.hpp>

#include "xml_translator.hpp"

//-----------------------------------------------------------------------------
// Enum, struct, aliases
namespace middleware {
/*!
 * Represents the unique identifier assignable to a task.
 */
typedef unsigned int TaskId;
/*! \enum TaskType
 * Represents the typology of task.
 */
typedef enum {
	/*!
	 * The task is an executable task, when such a task must be routed by a
	 * Manager, it is necessary to send, not only the TaskDescriptor, but the
	 * binaries of that task in order to let them to be executed correctly.
	 */
	kTaskExecutable = 0,
	/*!
	 * The task is just a Bash command, no need to grab and track Data.
	 */
	kTaskBashCommand = 1
} TaskType;
/*!
 * Represents the type for commands to execute in the case the task is a
 * bash command task.
 */
typedef std::string TaskCommand;
}
//-----------------------------------------------------------------------------
// Constants
namespace middleware {
/*!
 * Represents the highest ID assignable to a TaskDescriptor.
 */
const unsigned int kMaxTaskID = 16000;
/*!
 * Represents the lowest ID assignable to a TaskDescriptor.
 */
const unsigned int kMinTaskID = 1;
}
//-----------------------------------------------------------------------------
// Class definitions
namespace middleware {
/*! \class TaskDescriptor
 * \brief Represents a collection of information for a task.
 *
 * Thanks to this class, a task can be tracked and controlled during its journey
 * in the network. Thanks to information stored here, it is possible for the final
 * Worker, to recognize what is needed to execute the task.
 */
class TaskDescriptor : public xml::XmlTranslator {
public:
	/*!
	 * Constructs a command task with an invalid command specified. A TaskId
	 * is automatically created and assigned to the object.
	 */
	TaskDescriptor();
	/*!
	 * Constructs a TaskDescriptor with type automatically set to command type, user
	 * is request to specify the command.
	 * \param command The command to execute.
	 */
	explicit TaskDescriptor(TaskCommand command);
	/*!
	 * Builds a generic TaskDescriptor with the possibility to bind the task to
	 * a particular type.
	 * \param type Type of task to construct: executable or command.
	 */
	explicit TaskDescriptor(TaskType type);
	/*!
	 * Copy-constructor
	 */
	TaskDescriptor(const TaskDescriptor& task);
	/*!
	 * Destructor.
	 */
	virtual ~TaskDescriptor();
	/*!
	 * Gets the id of task.
	 * \return Returns the TaskId
	 */
	TaskId get_id() const {
		return this->_id;
	}
	/*!
	 * Sets task ID: this function should not be used because TaskDescriptor
	 * already thinks about this, an id conflict might occur if the id would
	 * be set manually.
	 * \param id TaskId to apply as task id for this task.
	 */
	void set_id(TaskId id) {
		this->_id = id;
	}
	/*!
	 * Gets the type of this task.
	 * \return Returns the type of the task.
	 */
	TaskType get_type() const {
		return this->_type;
	}
	/*!
	 * Sets the task type.
	 * \param type Type to apply to the task.
	 */
	void set_type(TaskType type) {
		this->_type = type;
	}
	/*!
	 * Gets the task command.
	 * \return Returns the command.
	 */
	TaskCommand get_command() const {
		return this->_command;
	}
	/*!
	 * Sets the task command.
	 * \param command Command to assign to the task.
	 */
	void set_command(TaskCommand command) {
		this->_command = command;
	}
	/*!
	 * Used when looking into an array of tasks and no desired task is found.
	 * An invalid task can be useful when a certain condition should not occur.
	 * \return Returns a TaskDescriptor that canoot be used to process a real task.
	 */
	static TaskDescriptor getInvalidTaskDescriptor() {
		TaskDescriptor task;
		task.set_id(0);
		return task;
	}
	/*!
	 * Implementation of XMLTranslator interface
	 */
	std::string ToXml() const;
protected:
	/*!
	 * Represents the unique reference to this task.
	 */
	TaskId _id;
	/*!
	 * Represents the type of task, it can be an executable or a bash command.
	 */
	TaskType _type;
	/*!
	 * If type is bash command, then this is the command to run.
	 */
	TaskCommand _command;
private:
	friend class boost::serialization::access;
	/*!
	 * BOOST serialization function.
	 */
	template<class Archive>
	void serialize(Archive & ar, const unsigned int version) {
		ar & _id;
		ar & _type;
		ar & _command;
	}
	/*!
	 * Gets a unique id for the task.
	 */
	TaskId createID();
}; /* TaskDescriptor */
} /* middleware */

#endif
